import { DomBuilder } from './dom-build.js'
import { EventEmitter, PluginManager } from './plugin-system/index.js'
import { createLogger } from './utils/logger.js'

const logger = createLogger('CodeEditor')

/**
 * 代码编辑器核心类
 * 基于插件架构的可扩展代码编辑器
 */
export class CodeEditor extends EventEmitter {
    constructor(el, config = {}) {
        super()

        if (!el) throw new Error('传入根节点初始化编辑器!')

        // 基础属性
        this.title = '未命名文件'
        this.config = config

        // 创建DomBuilder实例
        Object.assign(this, new DomBuilder(el))

        // 初始化插件管理器
        this.pluginManager = new PluginManager(this)

        // 撤销/重做相关属性
        this.history = [] // 撤销历史栈
        this.redoStack = [] // 重做栈
        this.isPerformingUndoRedo = false // 标志位，防止在Undo/Redo时记录历史
        this.historyMaxLength = 100 // 限制历史记录最大长度，防止内存溢出
        // 防抖
        this.historyDebounceTimer = null // 用于防抖的计时器 ID
        this.HISTORY_DEBOUNCE_DELAY = 300 // 防抖延迟时间 (毫秒)

        // 基础事件监听
        this._setupBaseEvents()

        // 初始化历史记录（在DOM创建完成后）
        this._saveHistory() // 保存初始状态
    }

    /**
     * 设置基础事件监听
     */
    _setupBaseEvents() {
        if (!this.editor) {
            logger.warn('未找到编辑器元素，跳过事件设置')
            return
        }

        // 基础输入事件
        this.editor.addEventListener('input', (e) => {
            // 如果是浏览器原生的撤销/重做操作，跳过处理
            if (e.inputType === 'historyUndo' || e.inputType === 'historyRedo') {
                return
            }

            this._updateEditor()
            this._updateStatus()
            // 保存历史记录，用于撤销功能
            this._debouncedSaveHistory()
            this.emit('editor:input', {
                value: this.editor.value,
                inputType: e.inputType,
                data: e.data,
                event: e
            })
        })

        // 键盘事件
        this.editor.addEventListener('keydown', (e) => {
            // 先发射事件让插件处理
            const handled = this.emit('editor:keydown', { event: e })
            
            // 如果插件没有处理，则由编辑器处理默认的撤销重做逻辑
            if (!handled) {
                // 拦截浏览器原生的撤销/重做操作
                if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {
                    e.preventDefault()
                    this.undo()
                    return
                }
                if ((e.ctrlKey || e.metaKey) && ((e.key === 'z' && e.shiftKey) || e.key === 'y')) {
                    e.preventDefault()
                    this.redo()
                    return
                }
            }
        })

        this.editor.addEventListener('keyup', () => {
            this._updateStatus()
            this.emit('editor:keyup')
        })

        // 滚动事件
        this.editor.addEventListener('scroll', () => {
            this._syncScroll()
        })

        // 点击事件
        this.editor.addEventListener('click', () => {
            this._updateStatus()
            this.emit('editor:click')
        })

        // 选择改变事件
        this.editor.addEventListener('selectionchange', () => {
            this.emit('editor:selectionchange')
        })

        // 焦点事件
        this.editor.addEventListener('focus', () => {
            this.emit('editor:focus')
        })

        this.editor.addEventListener('blur', () => {
            this.emit('editor:blur')
        })
    }

    /**
     * 更新编辑器
     * 更新行号
     */
    _updateEditor() {
        this._updateLineNumbers()
        this.emit('editor:update')
    }

    /**
     * 更新状态
     * 更新光标位置和字符计数等状态信息
     */
    _updateStatus() {
        const content = this.editor.value
        const cursorPosition = this.editor.selectionStart
        const lines = content.substring(0, cursorPosition).split('\n')
        const currentLine = lines.length
        const currentColumn = lines[lines.length - 1].length + 1
        this.lineCount.textContent = currentLine
        this.columnCount.textContent = currentColumn
        this.charCount.textContent = content.length
    }

    /**
     * 更新行号
     * 根据编辑器内容生成行号
     */
    _updateLineNumbers() {
        const lines = this.editor.value.split('\n')
        const lineCount = lines.length
        let numbers = ''
        for (let i = 1; i <= lineCount; i++) {
            numbers += i + '<br>'
        }
        this.lineNumbers.innerHTML = numbers
    }

    /**
     * 同步滚动
     * 保持行号区域与编辑器的滚动同步
     */
    _syncScroll() {
        this.lineNumbers.scrollTop = this.editor.scrollTop
        this.emit('editor:syncScroll', {
            scrollTop: this.editor.scrollTop,
            scrollLeft: this.editor.scrollLeft
        })
    }

    /**
     * 保存历史状态
     */
    _saveHistory() {
        // 避免在 Undo/Redo 过程中保存历史
        if (this.isPerformingUndoRedo) {
            return
        }

        if (!this.editor) {
            return
        }

        const currentState = this.editor.value
        const lastState = this.history.length > 0 ? this.history[this.history.length - 1] : null

        // 只有当内容真正改变时才保存
        if (currentState !== lastState) {
            this.history.push(currentState)
            // 限制历史记录长度
            if (this.history.length > this.historyMaxLength) {
                this.history.shift() // 移除最旧的记录
            }
        }
        // 每次有新的（不同的）输入时,清空重做栈,一旦有了新的输入，之前的重做操作就无效了
        this.redoStack = []
    }

    // 防抖版本的保存历史方法
    _debouncedSaveHistory() {
        // 清除之前的计时器
        if (this.historyDebounceTimer) {
            clearTimeout(this.historyDebounceTimer)
        }
        // 设置新的计时器，在延迟时间后执行 _saveHistory
        this.historyDebounceTimer = setTimeout(() => {
            this._saveHistory()
            this.historyDebounceTimer = null // 重置计时器 ID
        }, this.HISTORY_DEBOUNCE_DELAY)
    }

    // 撤销方法
    undo() {
        if (this.history.length > 1) { // 需要至少有一个前一状态
            this.isPerformingUndoRedo = true
            const currentState = this.history.pop() // 弹出当前状态
            this.redoStack.push(currentState) // 将当前状态放入重做栈
            const previousState = this.history[this.history.length - 1] // 获取前一状态
            // 设置编辑器内容
            this.editor.value = previousState

            // 设置光标位置到末尾
            this.editor.selectionStart = this.editor.selectionEnd = previousState.length
            // 更新UI
            this._updateEditor()
            this._updateStatus()
            // 触发语法高亮更新
            this.emit('editor:input', {
                value: this.editor.value,
                inputType: 'undo',
                isUndo: true
            })

            this.isPerformingUndoRedo = false
            this.emit('editor:undo', { value: previousState })
        }
    }

    // 重做方法
    redo() {
        if (this.redoStack.length > 0) {
            this.isPerformingUndoRedo = true
            const nextState = this.redoStack.pop() // 从重做栈弹出状态
            this.history.push(nextState) // 将该状态压入历史栈
            // 设置编辑器内容
            this.editor.value = nextState

            // 设置光标位置到末尾
            this.editor.selectionStart = this.editor.selectionEnd = nextState.length

            // 更新UI
            this._updateEditor()
            this._updateStatus()

            // 触发语法高亮更新
            this.emit('editor:input', {
                value: this.editor.value,
                inputType: 'redo',
                isRedo: true
            })
            this.isPerformingUndoRedo = false
            this.emit('editor:redo', { value: nextState })
        }
    }

    /**
     * 插件管理API
     */

    /**
     * 注册插件
     * @param {string} name - 插件名称
     * @param {class} PluginClass - 插件类
     */
    registerPlugin(name, PluginClass) {
        this.pluginManager.registerPlugin(name, PluginClass)
    }

    /**
     * 安装插件
     * @param {string} name - 插件名称
     * @param {Object} options - 插件配置
     */
    installPlugin(name, options = {}) {
        this.pluginManager.installPlugin(name, options)
    }

    /**
     * 卸载插件
     * @param {string} name - 插件名称
     */
    uninstallPlugin(name) {
        this.pluginManager.uninstallPlugin(name)
    }

    /**
     * 启用插件
     * @param {string} name - 插件名称
     */
    enablePlugin(name) {
        this.pluginManager.enablePlugin(name)
    }

    /**
     * 禁用插件
     * @param {string} name - 插件名称
     */
    disablePlugin(name) {
        this.pluginManager.disablePlugin(name)
    }

    /**
     * 获取插件
     * @param {string} name - 插件名称
     * @returns {BasePlugin|null} 插件实例
     */
    getPlugin(name) {
        return this.pluginManager.getPlugin(name)
    }

    /**
     * 批量配置插件
     * @param {Object} config - 插件配置
     */
    configurePlugins(config) {
        this.pluginManager.installPluginsFromConfig(config)
    }

    /**
     * 获取所有插件信息
     * @returns {Array} 插件信息数组
     */
    getAllPlugins() {
        return this.pluginManager.getAllPlugins()
    }

    /**
     * 销毁编辑器
     */
    destroy() {
        this.pluginManager.destroy()
        this.removeAllListeners()
    }
}